package jaoso.framework.util;

import jaoso.framework.domain.Account;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.DynaBean;
import org.apache.commons.beanutils.DynaProperty;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.beans.PropertyDescriptor;

import java.lang.reflect.InvocationTargetException;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * @author Edgeloner
 * @since 2004/6/23
 *  
 */
public class MyBeanUtils extends BeanUtils
{
    /** DOCUMENT ME! */
    private static Log log = LogFactory.getLog(MyBeanUtils.class);

    /**
     * default constructor
     */
    public MyBeanUtils()
    {
        super();
    }

    /**
     * override BeanUtils method copyProperties, support not copy null or blank
     * property
     * 
     * @param dest
     *            DOCUMENT ME!
     * @param orig
     *            DOCUMENT ME!
     * 
     * @throws IllegalAccessException
     *             DOCUMENT ME!
     * @throws InvocationTargetException
     *             DOCUMENT ME!
     * @throws IllegalArgumentException
     *             DOCUMENT ME!
     */
    public static void copyProperties(Object dest, Object orig)
            throws IllegalAccessException, InvocationTargetException
    {
        // Validate existence of the specified beans
        if (dest == null)
        {
            throw new IllegalArgumentException("No destination bean specified");
        }

        if (orig == null)
        {
            throw new IllegalArgumentException("No origin bean specified");
        }

        if (log.isDebugEnabled())
        {
            log.debug("BeanUtils.copyProperties(" + dest + ", " + orig + ")");
        }

        // Copy the properties, converting as necessary
        if (orig instanceof DynaBean)
        {
            DynaProperty[] origDescriptors = ((DynaBean) orig).getDynaClass()
                    .getDynaProperties();

            for (int i = 0; i < origDescriptors.length; i++)
            {
                String name = origDescriptors[i].getName();

                if (PropertyUtils.isWriteable(dest, name))
                {
                    Object value = ((DynaBean) orig).get(name);

                    if (value == null)
                    {
                        continue;
                    }

                    if (value instanceof String
                            && MyUtils.isBlank((String) value))
                    {
                        continue;
                    }

                    copyProperty(dest, name, value);
                }
            }
        } else if (orig instanceof Map)
        {
            Iterator names = ((Map) orig).keySet().iterator();

            while (names.hasNext())
            {
                String name = (String) names.next();

                if (PropertyUtils.isWriteable(dest, name))
                {
                    Object value = ((Map) orig).get(name);

                    if (value == null)
                    {
                        continue;
                    }

                    if (value instanceof String
                            && MyUtils.isBlank((String) value))
                    {
                        continue;
                    }

                    copyProperty(dest, name, value);
                }
            }
        } else
        /* if (orig is a standard JavaBean) */
        {
            PropertyDescriptor[] origDescriptors = PropertyUtils
                    .getPropertyDescriptors(orig);

            for (int i = 0; i < origDescriptors.length; i++)
            {
                String name = origDescriptors[i].getName();

                if ("class".equals(name))
                {
                    continue; // No point in trying to set an object's class
                }

                if (PropertyUtils.isReadable(orig, name)
                        && PropertyUtils.isWriteable(dest, name))
                {
                    try
                    {
                        Object value = PropertyUtils.getSimpleProperty(orig,
                                name);

                        if (value == null)
                        {
                            continue;
                        }

                        if (value instanceof String
                                && MyUtils.isBlank((String) value))
                        {
                            continue;
                        }

                        copyProperty(dest, name, value);
                    } catch (NoSuchMethodException e)
                    {
                        ; // Should not happen
                    }
                }
            }
        }
    }

    /**
     * DOCUMENT ME!
     * 
     * @param args
     *            DOCUMENT ME!
     */
    public static void main(String[] args)
    {
        Map a = new HashMap();
        Map b = new HashMap();
        a.put("a1", "11111111");
        a.put("a2", "22222222");
        a.put("a3", "33333333");
        b.put("a1", "11111111");
        b.put("a2", null);
        b.put("a3", "");
        System.out.println(a);
        System.out.println(b);

        Account aa = new Account();
        Account bb = new Account();
        aa.setId(null);
        aa.setName("aa");
        bb.setId("id");
        bb.setName("bb");

        try
        {
            // BeanUtils.copyProperties(a,b);
            System.out.println(aa.getId());
            System.out.println(aa.getName());
            System.out.println("bb" + bb.getId());
            System.out.println("bb" + bb.getName());

            //copyProperty(bb,"id",null);
            copyProperties(bb, aa);
            System.out.println(aa.getId());
            System.out.println(aa.getName());
            System.out.println("bb" + bb.getId());
            System.out.println("bb" + bb.getName());
        } catch (IllegalAccessException e)
        {
            e.printStackTrace();
        } catch (InvocationTargetException e)
        {
            e.printStackTrace();
        }
    }
}